import {Box3} from './Box3.js';
import {Vector3} from './Vector3.js';

const _box = /*@__PURE__*/ new Box3();

class Sphere {

  constructor(center, radius) {

    this.center = (center !== undefined) ? center : new Vector3();
    this.radius = (radius !== undefined) ? radius : -1;

  }

  set(center, radius) {

    this.center.copy(center);
    this.radius = radius;

    return this;

  }

  setFromPoints(points, optionalCenter) {

    const center = this.center;

    if (optionalCenter !== undefined) {

      center.copy(optionalCenter);

    } else {

      _box.setFromPoints(points).getCenter(center);

    }

    let maxRadiusSq = 0;

    for (let i = 0, il = points.length; i < il; i++) {

      maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));

    }

    this.radius = Math.sqrt(maxRadiusSq);

    return this;

  }

  clone() {

    return new this.constructor().copy(this);

  }

  copy(sphere) {

    this.center.copy(sphere.center);
    this.radius = sphere.radius;

    return this;

  }

  isEmpty() {

    return (this.radius < 0);

  }

  makeEmpty() {

    this.center.set(0, 0, 0);
    this.radius = -1;

    return this;

  }

  containsPoint(point) {

    return (point.distanceToSquared(this.center) <= (this.radius * this.radius));

  }

  distanceToPoint(point) {

    return (point.distanceTo(this.center) - this.radius);

  }

  intersectsSphere(sphere) {

    const radiusSum = this.radius + sphere.radius;

    return sphere.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);

  }

  intersectsBox(box) {

    return box.intersectsSphere(this);

  }

  intersectsPlane(plane) {

    return Math.abs(plane.distanceToPoint(this.center)) <= this.radius;

  }

  clampPoint(point, target) {

    const deltaLengthSq = this.center.distanceToSquared(point);

    if (target === undefined) {

      console.warn('THREE.Sphere: .clampPoint() target is now required');
      target = new Vector3();

    }

    target.copy(point);

    if (deltaLengthSq > (this.radius * this.radius)) {

      target.sub(this.center).normalize();
      target.multiplyScalar(this.radius).add(this.center);

    }

    return target;

  }

  getBoundingBox(target) {

    if (target === undefined) {

      console.warn('THREE.Sphere: .getBoundingBox() target is now required');
      target = new Box3();

    }

    if (this.isEmpty()) {

      // Empty sphere produces empty bounding box
      target.makeEmpty();
      return target;

    }

    target.set(this.center, this.center);
    target.expandByScalar(this.radius);

    return target;

  }

  applyMatrix4(matrix) {

    this.center.applyMatrix4(matrix);
    this.radius = this.radius * matrix.getMaxScaleOnAxis();

    return this;

  }

  translate(offset) {

    this.center.add(offset);

    return this;

  }

  equals(sphere) {

    return sphere.center.equals(this.center) && (sphere.radius === this.radius);

  }

}


export {Sphere};
